﻿/**********************************************************************
 * @file   FITKSpectraAlgorithm.h
 * @brief  频谱算法类
 * @author liuzhonghua (liuzhonghuaszch@163.com)
 * @date   2024-12-03
 *********************************************************************/
#ifndef _FITKSpectraAlgorithm_H
#define _FITKSpectraAlgorithm_H

#include "FITKAcousticsPhysicsAPI.h"
#include "FITKAcousticsAbstractSpectra.h"

namespace Acoustics
{
    /**
     * @brief  频谱算法类
     * @author liuzhonghua (liuzhonghuaszch@163.com)
     * @date   2024-12-03
     */
    class FITKAcousticsPhysicsAPI FITKSpectraAlgorithm
    {
    public:
        /**
         * @brief    构造函数
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        explicit FITKSpectraAlgorithm(FITKAcousticsAbstractSpectra* spectra);
        /**
         * @brief    析构
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        virtual ~FITKSpectraAlgorithm();
        /**
         * @brief    设置DB配置计算
         * @param[i] dB 是否启用DB计算
         * @param[i] dBValue 零分贝基准值
         * @return   void
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        void setDBAlgConfig(bool dB, double dBValue);
        /**
         * @brief    设置A权计算
         * @param[i] aWeighting 是否启用A权计算
         * @return   void
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        void setAWeighting(bool aWeighting);
        /**
         * @brief    设置计算类型
         * @param[i] type 
         *           0:RMS 
         *           1:PSD in (unit)^2/Hz 
         *           2:PSD in g^2/Hz
         * @return   void
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-04
         */
        void setCalcType(int type);
        /**
         * @brief    开始计算
         * @param[i] direction 计算方向 ：true-正向计算 false-反向计算
         * @param[i] spectra 设置频谱数据，如果为空就提取数据对象数据进行计算
         * @return   bool 状态
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool startCalc(bool direction, QList<Acoustics::SpectraValue> spectra = QList<Acoustics::SpectraValue>());
        /**
         * @brief    计算DB
         * @param[i] direction 计算方向 ：true-正向计算 false-反向计算
         * @param[i] spectra 设置频谱数据，如果为空就提取数据对象数据进行计算
         * @return   bool 状态
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool calcDBData(bool direction, QList<Acoustics::SpectraValue> spectra = QList<Acoustics::SpectraValue>());
        /**
         * @brief    计算A权
         * @param[i] direction 计算方向 ：true-正向计算 false-反向计算
         * @param[i] spectra 设置频谱数据，如果为空就提取数据对象数据进行计算
         * @param[i] A权倍率（PSD下A权是RMS下的两倍）
         * @return   bool 状态
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool calcAWeighting(bool direction, QList<Acoustics::SpectraValue> spectra = QList<Acoustics::SpectraValue>(), int rate = 1);
        /**
         * @brief    计算PSD
         * @param[i] direction 计算方向 ：true-正向计算 false-反向计算
         * @param[i] spectra 设置频谱数据，如果为空就提取数据对象数据进行计算
         * @return   bool 状态
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool calcPSD(bool direction, QList<Acoustics::SpectraValue> spectra = QList<Acoustics::SpectraValue>());
        /**
         * @brief    获取结果
         * @return   QList<Acoustics::SpectraValue>
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        QList<Acoustics::SpectraValue> getResults();
        /**
         * @brief    清空
         * @author   BaGuijun (baguijun@163.com)
         * @date     2024-12-10
         */
        void clear();
    protected:
        /**
         * @brief    计算dB数据
         * @return   void
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool calcDBData();
        /**
         * @brief    计算A权数据
         * @param[i] A权倍率（PSD下A权是RMS下的两倍）
         * @return   void
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-03
         */
        bool calcAWeighting(int rate = 1);
        /**
         * @brief    psd计算
         * psd/g正向计算时需要先计算为psd m/s，计算的基值为psd m/s;
         * 反向计算同理，计算后的结果为psd m/s
         * @return   bool
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-04
         */
        bool calcPSD();

    private:
        /**
         * @brief    获取DB计算系数
         * @return   double
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-04
         */
        double getDBCoefficient();
        /**
         * @brief    获取A权值
         * @param[i] freq 
         * @return   double
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-04
         */
        double getAWeightingValue(double freq);
        /**
         * @brief   获取PSD转换的数值 
         * @param[i] freq
         * @return   double
         * @author   liuzhonghua (liuzhonghuaszch@163.com)
         * @date     2024-12-04
         */
        double getPSDConverValue(double freq);
        /**
         * @brief   获取标准倍频程PSD1数值
         * @param[i] freq
         * @return   double
         * @author  XingXuanCi (xingxuanci@diso.cn)
         * @date    2024-11-25
         */
        double getStandardOctavePSD1Value(double freq);
        /**
         * @brief   获取标准倍频程PSD2数值
         * @param[i] freq
         * @return   double
         * @author  XingXuanCi (xingxuanci@diso.cn)
         * @date    2024-11-25
         */
        double getStandardOctavePSD2Value(double freq);
        /**
         * @brief   获取标准三分之一倍频程PSD1数值
         * @param[i] freq
         * @return   double
         * @author  XingXuanCi (xingxuanci@diso.cn)
         * @date    2024-11-25
         */
        double getStandard1Of3rdOctavePSD1Value(double freq);
        /**
         * @brief   获取标准三分之一倍频程PSD2数值
         * @param[i] freq
         * @return   double 
         * @author  XingXuanCi (xingxuanci@diso.cn)
         * @date    2024-11-25
         */
        double getStandard1Of3rdOctavePSD2Value(double freq);

    protected:
        /**
         * @brief  频谱数据对象
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-04
         */
        FITKAcousticsAbstractSpectra* _spectraDataObj{};
        /**
         * @brief  频谱数据
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        QList<Acoustics::SpectraValue> _spectraData{};
        /**
         * @brief  dB配置
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        QPair<bool, double> _dBConfig{ false, 0.0 };
        /**
         * @brief  A权配置
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        bool _aWeighting{ false };
        /**
         * @brief  0:RMS 
         *         1:PSD in (unit)^2/Hz 
         *         2:PSD in g^2/Hz
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-04
         */
        int _calcType{ 0 };
        /**
         * @brief  计算方向 true-正向计算 false-反向计算
         * @author liuzhonghua (liuzhonghuaszch@163.com)
         * @date   2024-12-03
         */
        bool _algDirection{ false };
    };
}

#endif
